package net.p2pcdn.core.order.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import net.p2pcdn.core.product.domain.Product;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 服务合约 每月生产一个
 *
 * @author zx
 */
@Getter
@Setter
@NoArgsConstructor
public class Contract {
    private static final Logger logger = LoggerFactory.getLogger(Contract.class);
    public static final int CLOSED = 0;
    public static final int UN_EFFECTIVE = 1;
    public static final int EFFECTIVE = 2;
    private int id;
    private int orderId;
    private int productId;
    private int userId;
    private Date expireTime;
    private Date startTime;
    private BigDecimal standardQuantity;
    private BigDecimal remainingQuantity;
    private BigDecimal extraQuantity;
    private List<CDNDomain> domains;
    private Date createTime;
    private int creator;
    private Date modifyTime;
    private int modifier;
    private int status = UN_EFFECTIVE;
    private String domainString;

    private BigDecimal getLeftQuantity() {
        extraQuantity = extraQuantity == null ? new BigDecimal("0") : extraQuantity;
        return extraQuantity.add(remainingQuantity);
    }

    public boolean isExpired() {
        if (getExpireTime() != null) {
            return getExpireTime().compareTo(new Date()) < 0;
        }
        return true;
    }

    protected Contract(Order order, Product product, String domainString, Date startTime, Date expireTime) {
        this.orderId = order.getId();
        this.userId = order.getBuyer();
        this.standardQuantity = product.getAmount();
        this.remainingQuantity = this.standardQuantity;
        this.extraQuantity = new BigDecimal("0");
        this.startTime = startTime;
        this.expireTime = expireTime;
        this.createTime = new Date();
        this.creator = order.getCreator();
        this.modifyTime = new Date();
        this.modifier = order.getCreator();
        this.domainString = domainString;
        this.productId = product.getId();
    }

    public static List<Contract> generateContracts(Order order,Date lastUnEffectiveDate, Product product, String domainString) {
        List<Contract> contracts = new LinkedList<>();
        int length = product.getUnitType() == Product.MONTH ? product.getStep() : product.getStep() * 12;
        length = order.getItemNum() * length;
        Date firstDate = null;
        if(lastUnEffectiveDate == null){
            firstDate = new Date();
        }else{
            firstDate = DateUtils.addMilliseconds(lastUnEffectiveDate,1);
        }
        Date expireDate = DateUtils.addMonths(firstDate,1);
        for (int i = 0; i < length; i++) {
            contracts.add(new Contract(order, product, domainString, firstDate, expireDate));
            firstDate = DateUtils.addMilliseconds(expireDate, 1);
            logger.debug("-------------------first date {}--------------------------", firstDate);
            expireDate = DateUtils.addMonths(firstDate, 1);
            logger.debug("-------------------expire date {}--------------------------", expireDate);
        }
        return contracts;
    }

    public List<String> resolveFormattedDomains() {
        if (StringUtils.isNotBlank(domainString)) {
            String regex = "[,;，；\n]";
            String[] values = this.domainString.split(regex);
            return Stream.of(values).filter(StringUtils::isNoneBlank).distinct().collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    public void buildCdnDomains() {
        if (this.id == 0) {
            throw new RuntimeException("save contract before call this method");
        }
        List<CDNDomain> domains = new ArrayList<>();
        resolveFormattedDomains().forEach(item -> domains.add(new CDNDomain(this.id, item)));
        this.setDomains(domains);
    }
}